package org.fearsomej.list.servlet;

import java.io.IOException;
import java.security.GeneralSecurityException;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.Query;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.fearsomej.list.domain.DataUser;
import org.fearsomej.list.domain.FearsomeCalendarEntry;
import org.fearsomej.list.domain.MappedDomainClass;
import org.fearsomej.list.server.data.EMF;

import com.google.appengine.api.users.User;
import com.google.appengine.api.users.UserService;
import com.google.appengine.api.users.UserServiceFactory;
import com.google.gdata.client.http.AuthSubUtil;
import com.google.gdata.util.AuthenticationException;

public class AuthenticationServlet extends HttpServlet {

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		UserService userService = UserServiceFactory.getUserService();
		User user = userService.getCurrentUser();
		if (user == null) {
			String thisUrl = req.getRequestURI();
			try {
				resp.sendRedirect(
						userService.createLoginURL(thisUrl));
			} catch (IOException e) {
				e.printStackTrace();
				throw new RuntimeException(e);
			}
		} else {

			DataUser dataUser = getDataUser();

			FearsomeCalendarEntry returnEntry = null;
			if (dataUser.getCalendarSessionToken() == null) {
				String onetimeUseToken = null;
				if (req.getParameter("token") != null) {
					onetimeUseToken = AuthSubUtil
							.getTokenFromReply(req
									.getQueryString());
				}
				if (onetimeUseToken == null) {
					String requestUrl = AuthSubUtil.getRequestUrl(
							req.getRequestURL().toString(),
							"http://www.google.com/calendar/feeds/", false,
							true);
					try {
						resp.sendRedirect(requestUrl);
					} catch (IOException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					return;
				} else {
					String sessionToken = null;
					try {
						sessionToken = AuthSubUtil.exchangeForSessionToken(
								onetimeUseToken, null);
						dataUser.setCalendarSessionToken(sessionToken);
						persistEntity(dataUser);
					} catch (AuthenticationException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					} catch (IOException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					} catch (GeneralSecurityException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					
				}
			}
		}
		req.getRequestDispatcher("/index.jsp").forward(req, resp);
	}
	
	protected void persistEntity(MappedDomainClass entity) {
		EntityManager em = EMF.get().createEntityManager();
		try {
			em.persist(entity);
		} finally {
			em.close();
		}
	}

	protected DataUser getDataUser() {
		UserService userService = UserServiceFactory.getUserService();
		User user = userService.getCurrentUser();
		EntityManager em = EMF.get().createEntityManager();
		DataUser dataUser = null;
		try {
			Query query = em
					.createQuery("select du from DataUser du where du.userId = :userId");
			query.setParameter("userId", user.getUserId());
			List<DataUser> users = query.getResultList();
			if (users != null && users.size() > 0) {
				dataUser = users.get(0);
			}
			if (dataUser == null) {
				dataUser = new DataUser();
				dataUser.setUserId(user.getUserId());
				dataUser.setNickname(user.getNickname());
				em.persist(dataUser);
			}
		} finally {
			em.close();
		}
		return dataUser;
	}

}
